package registnet.records;

import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Vector;

import resources.Constants;

public class Transcript {

	private Student student;
	private List<CourseTaken> courses = new Vector<CourseTaken>();
	
	
	/**
	 * Default constructor
	 * 
	 * @param student - The student who owns the transcript
	 */
	public Transcript(Student student){
		this.student = student;
	}
	
	
	/**
	 * Gets the student who owns the transcript
	 * 
	 * @return	The student who owns the transcript
	 */
	public Student getStudent(){
		return this.student;
	}
	
	
	/**
	 * Sets the student who owns the transcript
	 * 
	 * @param student - The student who owns the transcript
	 */
	public void setStudent(Student student){
		this.student = student;
	}
	
	
	/**
	 * Gets the courses included in the transcript
	 * 
	 * @return	The courses included in the transcript
	 */
	public List<CourseTaken> getCourses(){
		return this.courses;
	}
	
	
	/**
	 * Adds the course into the transcript
	 * 
	 * @param course - The course to add
	 */
	public void addCourse(CourseTaken course){
		this.courses.add(course);
	}
	
	
	/**
	 * Updates the removal/completion grade of the course
	 * 
	 * @param courseCode - The code assigned to the course
	 * @param grade - The grade obtained of the course taken to be updated
	 */
	public void updateReExamCourse(String courseCode, double grade){
		for(int i=courses.size()-1; i>=0; i--){
			CourseTaken courseTaken = (CourseTaken)courses.get(i);
			if(courseTaken.getCourseCode().equals(courseCode) && (courseTaken.getGrade()==Constants.MAP_GRADE_KEY.get("INC.")  || courseTaken.getGrade()==Constants.MAP_GRADE_KEY.get("4.00")) && courseTaken.getReExam()==0){
				((CourseTaken)courses.get(i)).setReExam(grade);
				break;
			}
		}
	}
	
	
	/**
	 * Gets the latest grade obtained
	 * 
	 * @param courseCode - The course 
	 * @return	The latest grade obtained
	 */
	public double getLatestGrade(ICourse course){
		double latestGrade = 0;
		ListIterator<CourseTaken> li = this.courses.listIterator();
		HashMap<String, ICourse> tempMap = new HashMap<String, ICourse>();
		List<ICourse> tempList = new Vector<ICourse>();
		ICourse latestCourse = null;
		while(li.hasNext()){
			ICourse c = li.next();
			if (c.getCourseCode().equals(course.getCourseCode())){
				if(!tempMap.containsKey(c.getCourseCode())){
					tempMap.put(c.getCourseCode(), c);
				}
				else{
					tempList.add(tempMap.get(c.getCourseCode()));
					tempMap.remove(c.getCourseCode());
					tempMap.put(c.getCourseCode(), c);
				}
				if (((CourseTaken)c).getReExam() != 0)
					latestGrade = ((CourseTaken)c).getReExam();
				else
					latestGrade = ((CourseTaken)c).getGrade();
				latestCourse = c;
			}
		}
		for(int i=0; i<tempList.size(); i++){
			this.courses.remove(tempList.get(i));
		}
		this.courses.remove(latestCourse);
		return latestGrade;
	}
	

	/*
	private List<CourseTaken> sortByTimeTaken(List<CourseTaken> courses){
		List<CourseTaken> retval = courses;
		int n = courses.size();
		for(int i=0; i<n-1; i++){
			for(int j=0; j<(n-1-i); j++){
				CourseTaken a = courses.get(j);
				CourseTaken b = courses.get(j+1);
				if(CourseTaken.compareByTimeTaken(a,b)>0){
					courses.set(j,b);
					courses.set(j+1,a);
				}
			}
		}
		return retval;
	}
	 */
	

	public boolean contains(CourseTaken course) {
		ListIterator<CourseTaken> li = this.courses.listIterator();
		while(li.hasNext())
			if(course.equals(li.next()))
				return true;
		return false;
	}
	

	/*
	public boolean contains(String courseCode) {
		ListIterator<CourseTaken> li = this.courses.listIterator();
		while(li.hasNext())
			if(courseCode.equals(li.next().getCourseCode()))
				return true;
		return false;
	}
	*/
	
	
	public List<CourseTaken> getCoursesTaken(int semester, int year) {
		List<CourseTaken> retval = new Vector<CourseTaken>();
		ListIterator<CourseTaken> li = this.courses.listIterator();
		while(li.hasNext()){
			CourseTaken tmpCourse = li.next();
			if(year==tmpCourse.getYearTaken() && semester==tmpCourse.getSemesterTaken())
				retval.add(tmpCourse);
		}
		return retval;
	}
	
	
	public List<CourseTaken> getCoursesTaken(int year) {
		List<CourseTaken> retval = new Vector<CourseTaken>();
		ListIterator<CourseTaken> li = this.courses.listIterator();
		while(li.hasNext()){
			CourseTaken tmpCourse = li.next();
			if(year==tmpCourse.getYearTaken())
				retval.add(tmpCourse);
		}
		return retval;
	}
	
	
	public CourseTaken getCourseTaken(String courseCode){
		ListIterator<CourseTaken> li = this.courses.listIterator();
		while(li.hasNext()){
			CourseTaken tmpCourse = li.next();
			if(tmpCourse.getCourseCode().contains(courseCode) || tmpCourse.getCourseName().contains(courseCode)){
				return (CourseTaken)tmpCourse;
			}
		}
		return null;
	}
	
	
	
	
	/*
	public CourseTaken getCourseTaken(String courseCode) {
		List<CourseTaken> listCourses = new Vector<CourseTaken>();
		ListIterator<CourseTaken> li = this.courses.listIterator();
		while(li.hasNext()){
			ICourse tmpCourse = li.next();
			if(courseCode.equals(tmpCourse.getCourseCode()))
				listCourses.add((CourseTaken)tmpCourse);
		}
		listCourses = sortByTimeTaken(listCourses);
		try{
			return listCourses.get(listCourses.size()-1);
		}catch(Exception e){
			return null;
		}
	}
	*/

	public double getGWA() {
		// TODO Auto-generated method stub
		return 0;
	}
	
	
	public int getUnitsCredited() {
		// TODO Auto-generated method stub
		return 0;
	}

	
	public boolean isCompleted(String courseCode) {
		try{
			CourseTaken courseTaken = (CourseTaken)getCourseTaken(courseCode);
			if (courseTaken.getReExam() != 0){
				if (courseTaken.getReExam() != Constants.MAP_GRADE_KEY.get("5") && courseTaken.getReExam() != Constants.MAP_GRADE_KEY.get("U"))
					return true;
			}else if (courseTaken.getGrade() != 0){
				if (courseTaken.getGrade() != Constants.MAP_GRADE_KEY.get("5") && courseTaken.getGrade() != Constants.MAP_GRADE_KEY.get("DRP.") && courseTaken.getGrade() != Constants.MAP_GRADE_KEY.get("U"))
					return true;
			}
		}catch(NullPointerException e){
			return false;
		}
		return false;
	}
	
	
	public int getUnits(int semester, int year){
		ListIterator<CourseTaken> iter = this.courses.listIterator();
		int totalUnits = 0;
		while(iter.hasNext()){
			CourseTaken course = iter.next();
			if(course.getCourseCode().contains("PE ") || course.getCourseCode().contains("LTS ") || course.getCourseCode().contains("CWTS ") || course.getCourseCode().contains("ROTC "))
				continue;
			if(course.getYearTaken() == year && course.getSemesterTaken() == semester){
				totalUnits += course.getUnit();
			}
		}
		return totalUnits;
	}
	
}
